﻿using CommunityToolkit.Mvvm.Input;
using HandyControl.Expression.Shapes;
using ImageHandler.Models;
using Microsoft.Win32;
using OpenCvSharp;
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Windows.Media.Imaging;

namespace ImageHandler.ViewModels
{
    /// <summary>
    /// 在图像拍摄或是扫描过程中，获取到不规则的矩形，这样的图像若不预处理，对后期的处理过程中会造成较大的难度
    /// 需要通过透视变换来校正图像，得到正确的形状；
    /// </summary>
    public class E006_DefectDetectionViewModel : PartViewModel
    {
        public E006_DefectDetectionViewModel()
        {
            Header = "零件缺陷检测";
        }

        public override void Run(string path)
        {
            // 读取图像
            Mat src = Cv2.ImRead(path, ImreadModes.Color);
            if (src.Empty())
            {
                OperateLogAction?.Invoke("无法读取图像！");
                return;
            }
            Result.ReslutInfos.Clear();

            // 转换为灰度图像
            Mat grayMat = new Mat();
            Cv2.CvtColor(src, grayMat, ColorConversionCodes.BGR2GRAY);
            AddMatToResultInfos(grayMat, "原图->灰度图像");

            // 高斯模糊
            Mat blurMat = new Mat();
            Cv2.GaussianBlur(grayMat, blurMat, new Size(3, 3), 9, 9, BorderTypes.Default);
           /// Cv2.MedianBlur(grayMat, blurMat, 5);
            AddMatToResultInfos(blurMat, "灰度图像->高斯模糊");

            // 双边滤波
            Mat bilateralFilter = new Mat();
            Cv2.BilateralFilter(blurMat, bilateralFilter, 9, 25, 25);
            AddMatToResultInfos(bilateralFilter, "高斯模糊->双边滤波");

            Mat fastMat = new Mat();
            Cv2.FastNlMeansDenoising(bilateralFilter, fastMat, 9);
            AddMatToResultInfos(fastMat, "双边滤波->均值去噪");

            // 二值化
            Mat binaryMat = new Mat();
            Cv2.Threshold(fastMat, binaryMat, 210, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
            AddMatToResultInfos(binaryMat, "均值去噪->二值化");

            // 形态学操作
            Mat morphMat = new Mat();
            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3), new Point(-1, -1));
            Cv2.MorphologyEx(binaryMat, morphMat, MorphTypes.Open, kernel, new Point(-1, -1), 2);
            AddMatToResultInfos(morphMat, "二值化->形态学开操作");

            // 轮廓检测
            Point[][] contours;
            HierarchyIndex[] hierarchy;
            Cv2.FindContours(morphMat, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            //绘制结果图像
            Mat markRet = Mat.Zeros(src.Size(), MatType.CV_8UC3);
            RNG rng = new RNG(12345);
            double maxArea = 0;
            int index = -1;
            for (int i = 0; i < contours.Length; i++)
            {
                //面积过滤
                double area = Cv2.ContourArea(contours[i]);
                double length = Cv2.ArcLength(contours[i], false);
                if (area > maxArea)
                {
                    maxArea = area;
                    index = i;
                }
                if (length > 300 && length < 600)
                {
                    Cv2.DrawContours(markRet, contours, i, new Scalar(rng.Uniform(0, 255), rng.Uniform(0, 255), rng.Uniform(0, 255)), 6, LineTypes.Link4);
                }
            }
            AddMatToResultInfos(markRet, "轮廓检测");

        }
    }
}
